home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog 125
/
Freelog_MarsAvril2015_No125.iso
/
Musique
/
Quod Libet
/
quodlibet-3.3.0-installer.exe
/
bin
/
quodlibet
/
ext
/
events
/
mediaserver.pyc
(
.txt
)
< prev
next >
Wrap
Python Compiled Bytecode
|
2014-12-31
|
26KB
|
613 lines
# Source Generated with Decompyle++
# File: in.pyc (Python 2.7)
import os
import sys
if os.name == 'nt' or sys.platform == 'darwin':
from quodlibet.plugins import PluginNotSupportedError
raise PluginNotSupportedError
import tempfile
from gi.repository import Gtk, GdkPixbuf
import dbus
import dbus.service as dbus
from quodlibet import app
from quodlibet.plugins.events import EventPlugin
from quodlibet.parse import Pattern
from quodlibet.util.uri import URI
from quodlibet.util.dbusutils import DBusIntrospectable, DBusProperty
from quodlibet.util.dbusutils import dbus_unicode_validate as unival
BASE_PATH = '/org/gnome/UPnP/MediaServer2'
BUS_NAME = 'org.gnome.UPnP.MediaServer2.QuodLibet'
class MediaServer(EventPlugin):
PLUGIN_ID = 'mediaserver'
PLUGIN_NAME = _('UPnP AV Media Server')
PLUGIN_DESC = _('Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-Bus interface')
PLUGIN_ICON = Gtk.STOCK_CONNECT
PLUGIN_VERSION = '0.1'
def enabled(self):
try:
dbus.SessionBus()
except dbus.DBusException:
self.objects = []
return None
entry = EntryObject()
albums = AlbumsObject(entry, app.library)
song = SongObject(app.library, [
albums])
icon = Icon(entry)
self.objects = [
entry,
albums,
song,
icon]
def disabled(self):
for obj in self.objects:
obj.remove_from_connection()
for obj in self.objects:
obj.destroy()
del self.objects
import gc as gc
gc.collect()
class DBusPropertyFilter(DBusProperty):
'''Adds some methods to support the MediaContainer property filtering.'''
def get_properties_for_filter(self, interface, filter_):
props = self.get_properties(interface)
if '*' not in filter_:
props = [ p for p in props if p[1] in filter_ ]
return props
def get_values(self, properties, path = '/'):
result = { }
for iface, prop in properties:
result[prop] = self.get_value(iface, prop, path)
return result
class MediaContainer(object):
IFACE = 'org.gnome.UPnP.MediaContainer2'
ISPEC_PROP = '\n<property type="u" name="ChildCount" access="read"/>\n<property type="u" name="ItemCount" access="read"/>\n<property type="u" name="ContainerCount" access="read"/>\n<property type="b" name="Searchable" access="read"/>\n<property type="o" name="Icon" access="read"/>\n'
ISPEC = '\n<method name="ListChildren">\n <arg type="u" name="offset" direction="in"/>\n <arg type="u" name="max" direction="in"/>\n <arg type="as" name="filter" direction="in"/>\n <arg type="aa{sv}" name="arg_3" direction="out"/>\n</method>\n<method name="ListContainers">\n <arg type="u" name="offset" direction="in"/>\n <arg type="u" name="max" direction="in"/>\n <arg type="as" name="filter" direction="in"/>\n <arg type="aa{sv}" name="arg_3" direction="out"/>\n</method>\n<method name="ListItems">\n <arg type="u" name="offset" direction="in"/>\n <arg type="u" name="max" direction="in"/>\n <arg type="as" name="filter" direction="in"/>\n <arg type="aa{sv}" name="arg_3" direction="out"/>\n</method>\n<method name="SearchObjects">\n <arg type="s" name="query" direction="in"/>\n <arg type="u" name="offset" direction="in"/>\n <arg type="u" name="max" direction="in"/>\n <arg type="as" name="filter" direction="in"/>\n <arg type="aa{sv}" name="arg_4" direction="out"/>\n</method>\n\n<signal name="Updated"/>\n'
def __init__(self, optional = tuple()):
self.set_introspection(MediaContainer.IFACE, MediaContainer.ISPEC)
props = [
'ChildCount',
'ItemCount',
'ContainerCount',
'Searchable']
props += list(optional)
self.set_properties(MediaContainer.IFACE, MediaContainer.ISPEC_PROP, wl = props)
self.implement_interface(MediaContainer.IFACE, MediaObject.IFACE)
def emit_updated(self, path = '/'):
self.Updated(rel = path)
def ListChildren(self, offset, max_, filter_, path):
if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
return self.list_children(offset, max_, filter_, path)
return None.list_children(offset, max_, filter_)
ListChildren = dbus.service.method(IFACE, in_signature = 'uuas', out_signature = 'aa{sv}', rel_path_keyword = 'path')(ListChildren)
def ListContainers(self, offset, max_, filter_, path):
if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
return self.list_containers(offset, max_, filter_, path)
return None.list_containers(offset, max_, filter_)
ListContainers = dbus.service.method(IFACE, in_signature = 'uuas', out_signature = 'aa{sv}', rel_path_keyword = 'path')(ListContainers)
def ListItems(self, offset, max_, filter_, path):
if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
return self.list_items(offset, max_, filter_, path)
return None.list_items(offset, max_, filter_)
ListItems = dbus.service.method(IFACE, in_signature = 'uuas', out_signature = 'aa{sv}', rel_path_keyword = 'path')(ListItems)
def SearchObjects(self, query, offset, max_, filter_, path):
return []
SearchObjects = dbus.service.method(IFACE, in_signature = 'suuas', out_signature = 'aa{sv}', rel_path_keyword = 'path')(SearchObjects)
def Updated(self, rel = ''):
pass
Updated = dbus.service.signal(IFACE, rel_path_keyword = 'rel')(Updated)
class MediaObject(object):
IFACE = 'org.gnome.UPnP.MediaObject2'
ISPEC = '\n<property type="o" name="Parent" access="read"/>\n<property type="s" name="Type" access="read"/>\n<property type="o" name="Path" access="read"/>\n<property type="s" name="DisplayName" access="read"/>\n'
parent = None
def __init__(self, parent = None):
self.set_properties(MediaObject.IFACE, MediaObject.ISPEC)
if not parent:
pass
self.parent = self
class MediaItem(object):
IFACE = 'org.gnome.UPnP.MediaItem2'
ISPEC = '\n<property type="as" name="URLs" access="read"/>\n<property type="s" name="MIMEType" access="read"/>\n\n<property type="x" name="Size" access="read"/>\n<property type="s" name="Artist" access="read"/>\n<property type="s" name="Album" access="read"/>\n<property type="s" name="Date" access="read"/>\n<property type="s" name="Genre" access="read"/>\n<property type="s" name="DLNAProfile" access="read"/>\n\n<property type="i" name="Duration" access="read"/>\n<property type="i" name="Bitrate" access="read"/>\n<property type="i" name="SampleRate" access="read"/>\n<property type="i" name="BitsPerSample" access="read"/>\n\n<property type="i" name="Width" access="read"/>\n<property type="i" name="Height" access="read"/>\n<property type="i" name="ColorDepth" access="read"/>\n<property type="i" name="PixelWidth" access="read"/>\n<property type="i" name="PixelHeight" access="read"/>\n<property type="o" name="Thumbnail" access="read"/>\n\n<property type="o" name="AlbumArt" access="read"/>\n\n<property type="i" name="TrackNumber" access="read"/>\n'
def __init__(self, optional = tuple()):
props = [
'URLs',
'MIMEType'] + list(optional)
self.set_properties(MediaItem.IFACE, MediaItem.ISPEC, wl = props)
self.implement_interface(MediaItem.IFACE, MediaObject.IFACE)
class EntryObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable, dbus.service.Object):
PATH = BASE_PATH + '/QuodLibet'
DISPLAY_NAME = "@REALNAME@'s Quod Libet on @HOSTNAME@"
def __init__(self):
self._EntryObject__sub = []
DBusIntrospectable.__init__(self)
DBusPropertyFilter.__init__(self)
MediaObject.__init__(self)
MediaContainer.__init__(self, optional = [
'Icon'])
bus = dbus.SessionBus()
name = dbus.service.BusName(BUS_NAME, bus)
dbus.service.Object.__init__(self, bus, self.PATH, name)
def get_property(self, interface, name):
if interface == MediaContainer.IFACE:
if name == 'ChildCount':
return len(self._EntryObject__sub)
if None == 'ItemCount':
return 0
if None == 'ContainerCount':
return len(self._EntryObject__sub)
if None == 'Searchable':
return False
if None == 'Icon':
return Icon.PATH
if interface == MediaObject.IFACE:
if name == 'Parent':
return self.parent.PATH
if None == 'Type':
return 'container'
if None == 'Path':
return self.PATH
if None == 'DisplayName':
return self.DISPLAY_NAME
def destroy(self):
del self._EntryObject__sub
del self.parent
def register_child(self, child):
self._EntryObject__sub.append(child)
self.emit_properties_changed(MediaContainer.IFACE, [
'ChildCount',
'ContainerCount'])
def list_containers(self, offset, max_, filter_):
props = self.get_properties_for_filter(MediaContainer.IFACE, filter_)
if not max_ or offset + max_:
pass
end = None
result = []
for sub in self._EntryObject__sub[offset:end]:
result.append(sub.get_values(props))
return result
list_children = list_containers
def list_items(self, offset, max_, filter_):
return []
SUPPORTED_SONG_PROPERTIES = ('Size', 'Artist', 'Album', 'Date', 'Genre', 'Duration', 'TrackNumber')
class DummySongObject(MediaItem, MediaObject, DBusPropertyFilter, DBusIntrospectable):
''' A dummy song object that is not exported on the bus, but supports
the usual interfaces.
You need to assign a real song before using it, and have to pass
a path prefix.
The path of the song is /org/gnome/UPnP/MediaServer2/Song/<PREFIX>/SongID
This lets us reconstruct the original parent path:
/org/gnome/UPnP/MediaServer2/<PREFIX>
atm. a prefix can look like "Albums/123456"
'''
SUPPORTS_MULTIPLE_OBJECT_PATHS = False
__pattern = Pattern('<discnumber|<discnumber>.><tracknumber>. <title>')
def __init__(self, parent):
DBusIntrospectable.__init__(self)
DBusPropertyFilter.__init__(self)
MediaObject.__init__(self, parent)
MediaItem.__init__(self, optional = SUPPORTED_SONG_PROPERTIES)
def set_song(self, song, prefix):
self._DummySongObject__song = song
self._DummySongObject__prefix = prefix
def get_property(self, interface, name):
if interface == MediaObject.IFACE:
if name == 'Parent':
return BASE_PATH + '/' + self._DummySongObject__prefix
if None == 'Type':
return 'music'
if None == 'Path':
path = SongObject.PATH
path += '/' + self._DummySongObject__prefix + '/' + str(id(self._DummySongObject__song))
return path
if None == 'DisplayName':
return unival(self._DummySongObject__song.comma('title'))
if interface == MediaItem.IFACE:
if name == 'URLs':
return [
self._DummySongObject__song('~uri')]
if None == 'MIMEType':
mimes = self._DummySongObject__song.mimes
if mimes:
pass
return mimes[0]
if None == 'Size':
return self._DummySongObject__song('~#filesize')
if None == 'Artist':
return unival(self._DummySongObject__song.comma('artist'))
if None == 'Album':
return unival(self._DummySongObject__song.comma('album'))
if None == 'Date':
return unival(self._DummySongObject__song.comma('date'))
if None == 'Genre':
return unival(self._DummySongObject__song.comma('genre'))
if None == 'Duration':
return self._DummySongObject__song('~#length')
if None == 'TrackNumber':
return self._DummySongObject__song('~#track', 0)
class DummyAlbumObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable):
SUPPORTS_MULTIPLE_OBJECT_PATHS = False
__pattern = Pattern('<albumartist|<~albumartist~album>|<~artist~album>>')
def __init__(self, parent):
DBusIntrospectable.__init__(self)
DBusPropertyFilter.__init__(self)
MediaObject.__init__(self, parent)
MediaContainer.__init__(self)
self._DummyAlbumObject__song = DummySongObject(self)
def get_dummy(self, song):
self._DummyAlbumObject__song.set_song(song, 'Albums/' + str(id(self._DummyAlbumObject__album)))
return self._DummyAlbumObject__song
def set_album(self, album):
self._DummyAlbumObject__album = album
self.PATH = self.parent.PATH + '/' + str(id(album))
def get_property(self, interface, name):
if interface == MediaContainer.IFACE:
if name == 'ChildCount' or name == 'ItemCount':
return len(self._DummyAlbumObject__album.songs)
if None == 'ContainerCount':
return 0
if None == 'Searchable':
return False
if interface == MediaObject.IFACE:
if name == 'Parent':
return self.parent.PATH
if None == 'Type':
return 'container'
if None == 'Path':
return self.PATH
if None == 'DisplayName':
return unival(self._DummyAlbumObject__pattern % self._DummyAlbumObject__album)
def list_containers(self, offset, max_, filter_):
return []
def list_items(self, offset, max_, filter_):
songs = sorted(self._DummyAlbumObject__album.songs, key = (lambda s: s.sort_key))
dummy = self.get_dummy(None)
props = dummy.get_properties_for_filter(MediaItem.IFACE, filter_)
if not max_ or offset + max_:
pass
end = None
result = []
for song in songs[offset:end]:
result.append(self.get_dummy(song).get_values(props))
return result
list_children = list_items
class SongObject(MediaItem, MediaObject, DBusProperty, DBusIntrospectable, dbus.service.FallbackObject):
PATH = BASE_PATH + '/Song'
def __init__(self, library, users):
DBusIntrospectable.__init__(self)
DBusProperty.__init__(self)
MediaObject.__init__(self, None)
MediaItem.__init__(self, optional = SUPPORTED_SONG_PROPERTIES)
bus = dbus.SessionBus()
self.ref = dbus.service.BusName(BUS_NAME, bus)
dbus.service.FallbackObject.__init__(self, bus, self.PATH)
self._SongObject__library = library
self._SongObject__map = dict((lambda .0: pass)(self._SongObject__library.itervalues()))
self._SongObject__reverse = dict((lambda .0: pass)(self._SongObject__map.iteritems()))
self._SongObject__song = DummySongObject(self)
self._SongObject__users = users
signals = [
('changed', self._SongObject__songs_changed),
('removed', self._SongObject__songs_removed),
('added', self._SongObject__songs_added)]
self._SongObject__sigs = (map,)((lambda .0: (s, f) = .0self._SongObject__library.connect(s, f)), signals)
def __songs_changed(self, lib, songs):
props = [ p[1] for p in self.get_properties(MediaItem.IFACE) ]
for song in songs:
song_id = str(id(song))
if song_id not in self._SongObject__map:
continue
for user in self._SongObject__users:
prefix = user.get_prefix(song)
path = '/' + prefix + '/' + song_id
self.emit_properties_changed(MediaItem.IFACE, props, path)
def __songs_added(self, lib, songs):
for song in songs:
new_id = id(song)
self._SongObject__map[new_id] = song
self._SongObject__reverse[song] = new_id
def __songs_removed(self, lib, songs):
for song in songs:
del self._SongObject__map[self._SongObject__reverse[song]]
del self._SongObject__reverse[song]
def destroy(self):
for signal_id in self._SongObject__sigs:
self._SongObject__library.disconnect(signal_id)
def get_dummy(self, song, prefix):
self._SongObject__song.set_song(song, prefix)
return self._SongObject__song
def get_property(self, interface, name, path):
(prefix, song_id) = path[1:].rsplit('/', 1)
song = self._SongObject__map[int(song_id)]
return self.get_dummy(song, prefix).get_property(interface, name)
class AlbumsObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable, dbus.service.FallbackObject):
PATH = BASE_PATH + '/Albums'
DISPLAY_NAME = 'Albums'
def __init__(self, parent, library):
DBusIntrospectable.__init__(self)
DBusPropertyFilter.__init__(self)
MediaObject.__init__(self, parent)
MediaContainer.__init__(self)
bus = dbus.SessionBus()
self.ref = dbus.service.BusName(BUS_NAME, bus)
dbus.service.FallbackObject.__init__(self, bus, self.PATH)
parent.register_child(self)
self._AlbumsObject__library = library.albums
self._AlbumsObject__library.load()
self._AlbumsObject__map = dict((lambda .0: pass)(self._AlbumsObject__library.itervalues()))
self._AlbumsObject__reverse = dict((lambda .0: pass)(self._AlbumsObject__map.iteritems()))
signals = [
('changed', self._AlbumsObject__albums_changed),
('removed', self._AlbumsObject__albums_removed),
('added', self._AlbumsObject__albums_added)]
self._AlbumsObject__sigs = (map,)((lambda .0: (s, f) = .0self._AlbumsObject__library.connect(s, f)), signals)
self._AlbumsObject__dummy = DummyAlbumObject(self)
def get_dummy(self, album):
self._AlbumsObject__dummy.set_album(album)
return self._AlbumsObject__dummy
def get_path_dummy(self, path):
return self.get_dummy(self._AlbumsObject__map[int(path[1:])])
def __albums_changed(self, lib, albums):
for album in albums:
rel_path = '/' + str(id(album))
self.emit_updated(rel_path)
self.emit_properties_changed(MediaContainer.IFACE, [
'ChildCount',
'ItemCount',
'DisplayName'], rel_path)
def __albums_added(self, lib, albums):
for album in albums:
new_id = id(album)
self._AlbumsObject__map[new_id] = album
self._AlbumsObject__reverse[album] = new_id
self.emit_updated()
self.emit_properties_changed(MediaContainer.IFACE, [
'ChildCount',
'ContainerCount'])
def __albums_removed(self, lib, albums):
for album in albums:
del self._AlbumsObject__map[self._AlbumsObject__reverse[album]]
del self._AlbumsObject__reverse[album]
self.emit_updated()
self.emit_properties_changed(MediaContainer.IFACE, [
'ChildCount',
'ContainerCount'])
def get_prefix(self, song):
album = self._AlbumsObject__library[song.album_key]
return 'Albums/' + str(id(album))
def destroy(self):
for signal_id in self._AlbumsObject__sigs:
self._AlbumsObject__library.disconnect(signal_id)
def __get_albums_property(self, interface, name):
if interface == MediaContainer.IFACE:
if name == 'ChildCount':
return len(self._AlbumsObject__library)
if None == 'ItemCount':
return 0
if None == 'ContainerCount':
return len(self._AlbumsObject__library)
if None == 'Searchable':
return False
if interface == MediaObject.IFACE:
if name == 'Parent':
return self.parent.PATH
if None == 'Type':
return 'container'
if None == 'Path':
return self.PATH
if None == 'DisplayName':
return self.DISPLAY_NAME
def get_property(self, interface, name, path):
if path == '/':
return self._AlbumsObject__get_albums_property(interface, name)
return None.get_path_dummy(path).get_property(interface, name)
def __list_albums(self, offset, max_, filter_):
props = self.get_properties_for_filter(MediaContainer.IFACE, filter_)
albums = sorted(self._AlbumsObject__library, key = (lambda a: a.sort))
if not max_ or offset + max_:
pass
end = None
result = []
for album in albums[offset:end]:
result.append(self.get_dummy(album).get_values(props))
return result
def list_containers(self, offset, max_, filter_, path):
if path == '/':
return self._AlbumsObject__list_albums(offset, max_, filter_)
def list_items(self, offset, max_, filter_, path):
if path != '/':
return self.get_path_dummy(path).list_items(offset, max_, filter_)
def list_children(self, offset, max_, filter_, path):
if path == '/':
return self._AlbumsObject__list_albums(offset, max_, filter_)
return None.get_path_dummy(path).list_children(offset, max_, filter_)
class Icon(MediaItem, MediaObject, DBusProperty, DBusIntrospectable, dbus.service.Object):
PATH = BASE_PATH + '/Icon'
SIZE = 160
def __init__(self, parent):
DBusIntrospectable.__init__(self)
DBusProperty.__init__(self)
MediaObject.__init__(self, parent = parent)
MediaItem.__init__(self, optional = [
'Height',
'Width',
'ColorDepth'])
bus = dbus.SessionBus()
name = dbus.service.BusName(BUS_NAME, bus)
dbus.service.Object.__init__(self, bus, self.PATH, name)
self.implement_interface('org.gnome.UPnP.MediaItem1', MediaItem.IFACE)
theme = Gtk.IconTheme.get_default()
pixbuf = theme.load_icon('quodlibet', Icon.SIZE, 0)
pixbuf = pixbuf.scale_simple(Icon.SIZE, Icon.SIZE, GdkPixbuf.InterpType.BILINEAR)
self._Icon__depth = pixbuf.get_bits_per_sample()
self._Icon__f = f = tempfile.NamedTemporaryFile()
pixbuf.savev(f.name, 'png', [], [])
def get_property(self, interface, name):
if interface == MediaObject.IFACE:
if name == 'Parent':
return EntryObject.PATH
if None == 'Type':
return 'image'
if None == 'Path':
return Icon.PATH
if None == 'DisplayName':
return "I'm an icon \\o/"
if interface == MediaItem.IFACE:
if name == 'URLs':
return [
URI.frompath(self._Icon__f.name)]
if None == 'MIMEType':
return 'image/png'
if None == 'Width' or name == 'Height':
return Icon.SIZE
if None == 'ColorDepth':
return self._Icon__depth
def destroy(self):
pass